import axios from 'axios'
import dbUtils from '../libs/util.strotage'
import { XsyMessage } from '../libs/util.toast'
import { useDbStore } from '@/stores/db.js'

// 不能使用useRouter ,useRoute，他们需要在setup中调用执行后才能用
import router from '@/router'
// 创建 Axios 实例
const instance = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 60000
})
// 请求拦截器
instance.interceptors.request.use(
    (config) => {
        // 在请求发送之前可以进行一些处理，例如设置 token、添加请求头等
        config.headers['gm-session-id'] = dbUtils.get('token') // 临时token
        return config
    },
    () => {
        return Promise.reject()
    }
)

// 响应拦截器
instance.interceptors.response.use(
    (response) => {
        // 在接收到响应数据之前可以进行一些处理，例如解析响应数据、错误处理等
        // ...
        
        if (response.data.code == 10002) {
            location.href = import.meta.env.VITE_BASE_PATH;
            XsyMessage.error('账号已过期,请重新登录')
        } else if (response.data.code !== 0) {
            if(response.data.code != '10111' && response.data.code != '10146'){
                XsyMessage.error(response.data.message || '网络异常')
            }
            
            // 账户余额不足、余额预警做特殊处理
            return Promise.reject(response.data)
        }
        const contentType = response.headers['content-type']
        if (contentType === 'application/octet-stream' ||
            contentType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
            // 注意：Blob类型文件下载需要请求头参数添加 responseType:'blob'  下载 导出等功能需要
            downloadFile(response)
        } else {
            // 响应数据是有效的 JSON 格式，继续处理
            return Promise.resolve(response.data)
        }


    },
    (error) => {
        // 统一处理错误
        return handleRequestError(error)
    }
)

// 下载blob二进制文件
const downloadFile = (response) => {
    const url = window.URL.createObjectURL(new Blob([response.data]))
    const filename = response.headers['x-filename']

    axios.get(url, { responseType: 'blob' }).then((res) => {
        const blob = new Blob([res.data])
        if (window.navigator.msSaveBlob) {
            // 兼容 IE，使用 msSaveBlob 方法进行下载
            window.navigator.msSaveBlob(blob, decodeURIComponent(filename))
        } else {
            // 创建一个 <a> 元素
            const link = document.createElement('a')
            link.href = window.URL.createObjectURL(blob)
            link.setAttribute('download', decodeURIComponent(filename))
            // 模拟点击下载
            link.click()
            // 清理 URL 和 <a> 元素
            link.remove()
            window.URL.revokeObjectURL(url)
        }
    })
}

// 统一处理错误
const handleRequestError = (error) => {
    // 进行错误处理
    if (error.response) {
        // 服务器响应错误
        const status = error.response.status
        // 在这里可以进行错误处理逻辑，例如弹出错误提示、记录错误日志等
        switch (status) {
            case 400:
                console.error('参数校验失败:', error.response.data.message)
                XsyMessage.error(error.response.data.message || '参数校验失败')
                return Promise.reject(error.response.data.message ?? '参数json解析失败')
            case 401:
                console.error('未授权:', error.response.data.message)
                if (error.response.data.message === 'Token不存在或已过期') {
                    location.href = import.meta.env.VITE_BASE_PATH;
                    XsyMessage.error('账号已过期,请重新登录')
                    return Promise.reject({ error: 'Unauthorized', message: '账号已过期,请重新登录' })
                } else {
                    XsyMessage.error(error.response.data.message || '账号已过期,请重新登录')
                    return Promise.reject({ error: '401', message: error.response.data.message })
                }
            case 403:
                const db = useDbStore()
                db.removeAllInfo()
                location.href = import.meta.env.VITE_BASE_PATH;
                XsyMessage.error('账号已过期,请重新登录')
                return Promise.reject({ error: 'Unauthorized', message: '账号已过期,请重新登录' })
            case 404:
                console.error('404:', error.response.data.message)
                XsyMessage.error(error.response.data.message || '资源不存在')
                return Promise.reject({ error: '接口不存在', message: error.response.data.message })
            case 500:
                console.error('服务器内部错误:', error.response.data.message)
                XsyMessage.error(error.response.data.message || '服务器内部错误')
                return Promise.reject({ error: '服务器内部错误', message: error.response.data.message })
            default:
                XsyMessage.error('服务器响应错误')
                console.error('服务器响应错误:', error.response.data)
        }
    } else if (error.request) {
        // 请求未收到响应
        console.error('请求未收到响应:', error.request)
        XsyMessage.error('请求未收到响应')
        // 在这里可以进行错误处理逻辑，例如弹出错误提示、记录错误日志等
    } else {
        // 请求配置出错
        console.error('请求配置出错:', error.message)
        XsyMessage.error('请求配置出错')
        // 在这里可以进行错误处理逻辑，例如弹出错误提示、记录错误日志等
    }
}

// 封装请求方法
class AxiosService {
    constructor() {
        if (AxiosService.instance) {
            return AxiosService.instance
        }
        AxiosService.instance = this
    }

    // GET 请求
    get(url, params = null) {
        return instance.request({
            method: 'get',
            url,
            params
        })
    }

    // POST 请求
    post(url, data = null, params = null, responseType) {
        return instance.request({
            method: 'post',
            url,
            data,
            params,
            responseType
        })
    }

    // PUT 请求
    put(url, data = null, params = null) {
        return instance.request({
            method: 'put',
            url,
            data,
            params
        })
    }

    // DELETE 请求
    delete(url, data = null, params = null) {
        return instance.request({
            method: 'delete',
            url,
            data,
            params
        })
    }
}

// 创建 AxiosService 实例
const axiosService = new AxiosService()


// 通用下载方法
export const uploadImgUrl = import.meta.env.VITE_APP_BASE_API + '/api/v1/file/upload'

export const uploadFileUrl = import.meta.env.VITE_APP_BASE_API + '/console/api/actions/upload'// 图片上传路径（会验证文件类型，只能上传png/jpg格式）

// 导出实例化后的 AxiosService 对象
export default axiosService
